package com.leaf.u.basehttp.http.request;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import com.leaf.u.basehttp.http.DefaultConvert;
import com.leaf.u.basehttp.http.HttpCallback;
import com.leaf.u.basehttp.http.HttpEngine;
import com.leaf.u.basehttp.http.ResponseConvert;
import com.leaf.u.basehttp.http.inter.RequestInterceptor;
import com.leaf.u.basehttp.http.okimpl.LeafRequest;
import com.leaf.u.basehttp.http.response.ErrorResponse;
import com.leaf.u.basehttp.http.response.LeafResponse;
import com.leaf.u.basehttp.http.response.OnHttpResponse;
import com.leaf.u.basehttp.http.response.SuccessResponse;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by bz on 2017/5/17.
 */

public class AsyncCall implements Runnable {
    private HttpEngine httpEngine;
    private LeafRequest request;
    private OnHttpResponse callback;
    private List<RequestInterceptor> interceptors = new ArrayList<>();
    private ResponseConvert convert = new DefaultConvert();
    private String uid;

    public AsyncCall(HttpEngine httpEngine, LeafRequest builder) {
        this.request = builder;
        this.uid = builder.uid();
        this.httpEngine = httpEngine;
    }

    public AsyncCall(HttpEngine httpEngine,
                     LeafRequest builder,
                     List<RequestInterceptor> interceptors,
                     ResponseConvert convert) {
        this.request = builder;
        this.uid = builder.uid();
        this.httpEngine = httpEngine;
        //拦截器添加
        if (interceptors != null && interceptors.size() > 0) {
            this.interceptors.addAll(interceptors);
        }
        this.convert = convert;
    }

    public String uid() {
        return this.uid;
    }

    /**
     * 添加拦截器
     * @param interceptor
     * @return
     */
    public AsyncCall addInterceptor(RequestInterceptor interceptor) {
        this.interceptors.add(interceptor);
        return this;
    }

    public AsyncCall setResponseConvert(ResponseConvert convert) {
        this.convert = convert;
        return this;
    }

    public <T> void execute(HttpCallback<T> callback) {
        this.callback = callback;
        httpEngine.dispatcher().enqueue(this);
    }

    public AsyncCall execute() {
        httpEngine.dispatcher().enqueue(this);
        return this;
    }

    /**
     * 设置回调函数
     * @param callback
     * @param <T>
     */
    public <T> void setHttpCallback(HttpCallback<T> callback){
        this.callback = callback;
    }


    @Override
    public void run() {
        List<RequestInterceptor> interceptors = addIntercepter();
        RequestInterceptorChain chain = new RequestInterceptorChain(interceptors, this.request, this.httpEngine);
        boolean endding = false;
        while (!endding) {
            LeafResponse response = null;
            Object result = null;
            try {
                response = chain.proceed(request);
                result = convert.convert(callback.getType(), response);
                notice(result, response, null);
            } catch (Throwable e) {
                notice(result, response, e);
            } finally {
                endding = chain.isFinish();
            }
        }
        httpEngine.dispatcher().finished(this);
    }


    private void notice(final Object result, final LeafResponse response, final Throwable e) {

        new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (response != null && result != null) {
                    SuccessResponse.Builder successBuilder = new SuccessResponse.Builder<>();
                    successBuilder.setBody(result);
                    successBuilder.setHeaders(response.headers());
                    successBuilder.setOriginal(response.original());
                    callback.onSuccess(successBuilder.build());
                } else if (response != null) {
                    ErrorResponse.Builder errorBuilder = new ErrorResponse.Builder();
                    errorBuilder.setThrowable(e);
                    errorBuilder.setCode(response.code());
                    errorBuilder.setOriginal(response.original());
                    callback.onFailed(errorBuilder.build());
                } else {
                    ErrorResponse.Builder errorBuilder = new ErrorResponse.Builder();
                    errorBuilder.setThrowable(e);
                    callback.onFailed(errorBuilder.build());
                }
            }
        }.sendEmptyMessage(0);

    }
    private List<RequestInterceptor> addIntercepter() {
        List<RequestInterceptor> interceptors = new ArrayList<>();
        if (this.interceptors.size() > 0) {
            interceptors.addAll(this.interceptors);
        } else {
            interceptors.addAll(httpEngine.interceptors());
        }

        interceptors.add(new ServerInterceptor());

        return interceptors;
    }

}
